const jsonwebtoken = require('jsonwebtoken');

// 导入User模型
const User = require('../models/user');

const tokenConfig = require('../config/token');

const stringHelper = require('../utils/string.helper');

// 解构赋值
const {
    AUTH_SUCCESS,
    AUTH_FAILURE,
    CREATE_SUCCESS,
    CREATE_FAILURE,
    RETRIEVE_SUCCESS,
    RETRIEVE_FAILURE,
    RETRIEVE_ID_NOT_EXISTS,
    RETRIEVE_ACCOUNT_EXISTS,
    RETRIEVE_EMAIL_EXISTS,
    RETRIEVE_TEL_EXISTS,
    UPDATE_SUCCESS,
    UPDATE_FAILURE,
    DELETE_SUCCESS,
    DELETE_FAILURE
} = require('../constant/user');

// 用户列表
const list = (req,resp) => {
    // 经 jwtMiddleware 解析 请求头 中的 authorization 后，
    // 将数据绑定到 req 的 auth 属性
    User.findAll({
        attributes:['id','account','email','tel'],
        order: [ ['id', 'DESC'] , ['account', 'DESC'] ]
    }).then( rows => {
        return rows.map( u => u.dataValues );
    }).then( users => {
        let index = users.findIndex( u => u.id == req.auth.id );
        users.splice( index , 1 );
        // 将 RETRIEVE_SUCCESS 展开到新的对象中
        resp.json( { ...RETRIEVE_SUCCESS , result: users } );
    }).catch( reason => {
        // 将 RETRIEVE_FAILURE 展开到新的对象中
        resp.json( { ...RETRIEVE_FAILURE , reason: reason } );
    });
}

// 新增用户
const add = (req,resp)=>{
    let { account , email , tel , password } = req.body ;
    console.log( account , email , tel , password );
    
    // 生成用于对密码进行加密的盐值(参数4表示盐值字符串长度)
    const salt = stringHelper.random(4);

    // 采用随机生成的盐值对密码进行混淆后再加密
    password = stringHelper.encrypt( password , salt );

    const user = {
        account: account ? account : undefined ,
        email: email ? email : undefined,
        tel: tel ? tel : undefined,
        password,
        salt
    }

    User.create( user ).then( instance => {
        let id = instance.dataValues.id ;
        console.log( 'inserted id : ' , id );
        resp.json( { ...CREATE_SUCCESS , result: id });
    }).catch( cause => {
        let reason = ( cause instanceof Error ) ? cause.message : cause ;
        resp.json( { ...CREATE_FAILURE , reason });
    });
}

const map = {
    'account' : '账号',
    'email' : '邮箱',
    'tel' : '手机号',
}

// 处理登录操作
const signIn = (req,resp)=>{
    const { account , email , tel , password } = req.body ;
    console.log( account , email , tel , password );
    let fieldName = account ? 'account' : '' ;
    fieldName = email ? 'email' : fieldName ;
    fieldName = tel ? 'tel' : fieldName ;
    console.log( 'fieldName: ' , fieldName );

    // 根据确定下来的 fieldName 从 body 中获取参数值
    let fieldValue = req.body[ fieldName ];

    User.findOne({
        where: {
            // 通过 [ fieldName ] 来确定 名称
            [fieldName]: fieldValue
        }
    }).then( result => {
        console.log( 'result: ' ,result );
        // 若登录时使用的登录信息错误，则抛出异常终止后续操作
        if( !result ) {
            throw new Error( `${map[fieldName]}在系统中不存在` );
        }
        // 若登录信息正确则能够从数据库中查询到用户信息
        // 从 result 中获取 dataValues 作为 user 来使用
        let user = result.dataValues ;
        // 直接返回 user 对象
        return user ;
    }).then( user => {
        // 根据从数据库中查询到的盐值对用户输入的密码进行加密
        let encryped = stringHelper.encrypt( password , user.salt );
        // 检查密码是否正确
        // 用数据库中存储的 加密字符串 与 encryped 进行对比
        if( user.password != encryped ) {
            throw new Error( '登录密码错误' );
        }

        let payload = {
            id: user.id
        }

        let options = {
            expiresIn: tokenConfig.expiresIn , 
            algorithm: tokenConfig.algorithm
        }

        let token = jsonwebtoken.sign( payload, tokenConfig.secret, options );
        // 向客户端返回认证信息
        resp.json( { ...AUTH_SUCCESS , result: { token } } );
    }).catch( cause => {
        let reason = (cause instanceof Error ) ? cause.message : cause ;
        resp.json( { ...AUTH_FAILURE , reason } );
    });

}

// 检查认证
const check = (req,resp,next) => {
    // 因为经过 jwtMiddleware 处理后的 payload 会绑定到 req 的 auth 属性
    // 因此可以通过检查 req 对象上是否存在有效的 auth 来确定用户是否被认证(即用户是否已经登录)
    if( req.auth ) {
        // 若认证有效则继续调用下一个中间件
        next();
        return;
    }
    // 若未通过认证，则向客户端返回失败信息
    resp.json( AUTH_FAILURE );
}

// 查询用户(单个)
const load = (req,resp) => {
    // 根据路由路径中传递的参数值来查询
    let promise = User.findByPk( req.params.id );
    promise.then( result => {
        if( result ){
            return result.dataValues ;
        }
        throw new Error(`${id}在系统中不存在`);
    }).then( user => {
        delete user.salt;
        delete user.password;
        resp.json( { ...RETRIEVE_SUCCESS, result: user } );
    }).catch( cause => {
        let reason = cause.message ? cause.message : cause ;
        resp.json( { ...RETRIEVE_FAILURE, reason } );
    });
}

// 查询当前用户(已登录的用户)
const find = (req,resp) => {
    let promise = User.findByPk( req.auth.id );
    promise.then( result => {
        if( result ){
            return result.dataValues ;
        }
        throw new Error(`${id}在系统中不存在`);
    }).then( user => {
        delete user.salt;
        delete user.password;
        resp.json( { ...RETRIEVE_SUCCESS, result: user } );
    }).catch( cause => {
        let reason = cause.message ? cause.message : cause ;
        resp.json( { ...RETRIEVE_FAILURE, reason } );
    });
}

// 注册校验
const validator = (req,resp,next) => {
    const { account , email , tel , password } = req.body ;
    const exists = true ;
    User.findOne( { 
        where: { account } 
    }).then( user => {
        if( user ) {
            resp.json( RETRIEVE_ACCOUNT_EXISTS );
            return exists;
        }
        // 用 findOne 继续查找并将其返回的 Promise实例 继续返回
        return User.findOne( { where: { email } } );
    }).then( value => {
        if( value === exists ){
            return exists ;
        }
        if( value ) {
            resp.json( RETRIEVE_EMAIL_EXISTS );
            return exists;
        }
        // 用 findOne 继续查找并将其返回的 Promise实例 继续返回
        return User.findOne( { where: { tel } } );
    }).then( value => {
        if( value === exists ){
            return exists ;
        }
        if( value ) {
            resp.json( RETRIEVE_TEL_EXISTS );
            return exists;
        }
    }).then( value => {
        if( value === undefined ) {
            // 若 user 不存在则认为可以注册，继续调用下一个中间件即可
            next();
        }
    }).catch( cause => {
        let reason = cause instanceof Error ? cause.message : cause ;
        resp.json( { ...VALIDATE_FAILURE , reason } );
    });
}

// 删除用户
const remove = (req,resp) => {
    User.destroy({
        where: {
            id: req.params.id
        }
    }).then( count => {
        resp.json( { ...DELETE_SUCCESS , result: count } );
    }).catch( cause => {
        let reason = ( cause instanceof Error ) ? cause.message : cause ;
        resp.json( { ...DELETE_FAILURE , reason } );
    })
}

// 修改用户
const update = (req,resp) => {
  let { id , account , email , tel } = req.body;
  User.update({
    account,
    email,
    tel
  },{
    where: { id }
  }).then( result => {
    resp.json( { ...UPDATE_SUCCESS , result } );
  }).catch( cause => {
    let reason = ( cause instanceof Error ) ? cause.message : cause ;
    resp.json( { ...UPDATE_FAILURE , reason } );
  });
}

// 导出控制器中的方法
module.exports = {
    list,
    add,
    signIn,
    check,
    load,
    validator,
    remove,
    update,
    find
}